use axum::extract::{Path, Query};
use axum::{Router, Json};
use axum::routing::{get, post};
use serde::{Serialize,Deserialize};
use tower_cookies::Cookies;

use crate::models::{User, Comment, CreateComment, Guide, CreateGuide, UpdateComment, UpdateGuide,UpdateGuide2};
use crate::utils::cookie;
use crate::utils::cookie::get_user_from_cookies;
type RouterResult<T> = Result<T,String>;


// struct RouterResponse {

// }

#[derive(Deserialize,Serialize)]
struct GuideResponse{
    pub discription:String,
    pub status:String,
    pub guide_id:String,
    pub comment_id:String,
}

impl GuideResponse{
    pub fn ok(discription:String,guide_id:String,comment_id:String) -> GuideResponse {
        GuideResponse { discription, status: "ok".to_string(), guide_id, comment_id}
    }

    pub fn err(discription:String,guide_id:String,comment_id:String) -> GuideResponse {
        GuideResponse { discription, status: "err".to_string(), guide_id, comment_id}
    }

}


pub fn router() -> Router {
    Router::new()
        .route("/", get(index))
        .route("/make_comment", post(make_comment))
        .route("/delete_comment", get(delete_comment))
        .route("/update_comment", post(update_comment))
        .route("/make_guide", post(make_guide))
        .route("/update_guide", post(update_guide))
        .route("/update_guide2", post(update_guide2))
        .route("/delete_guide", get(delete_guide))
        .route("/apply_for_friend", get(apply_for_friend))
        .route("/recommend_to_friends",get(recommend_to_friend))
        .route("/get_all",get(get_all_guides_written_by_current_user))
}

async fn index(cookies:Cookies) -> RouterResult<String> {
    let user_id = cookie::get_user_id_from_cookie(cookies).unwrap();

    let user_id: i32 = user_id.parse().unwrap();

    let user = User::fetch_one_by_id(user_id).await.map_err(|err| err.to_string())?;

    Ok(format!("欢迎来到guide 特权首页，{}！",user.nickname))

}

// async fn get_user_from_cookies(cookies:Cookies) -> Result<User,String> {
//     let user_id = cookie::get_user_id_from_cookie(cookies).unwrap();

//     let user_id: i32 = user_id.parse().unwrap();

//     let user = User::fetch_one_by_id(user_id).await.map_err(|err| err.to_string())?;
//     Ok(user)

// }



/// 发表攻略评论
async fn make_comment(Json(comment):Json<CreateComment>,cookies:Cookies) -> Json<GuideResponse> {
    let user = get_user_from_cookies(cookies).await;
    if let Err(err) = user {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    
    let guide_id = comment.of_id; //要评论的攻略的id

    // 建立一个comment
    let comment_id = Comment::insert(user.unwrap().id, comment.content, comment.rate, "status".to_string()).await.map_err(|err| err.to_string());

    if let Err(err) = comment_id {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    let comment_id = comment_id.unwrap();

    let res = Guide::push_comment_by_id(guide_id, comment_id).await.map_err(|err| err.to_string());
    if let Err(err) = res {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }

    // Json(serde_json::json!({
    //     "comment_id":comment_id
    // }))
    Json(GuideResponse::ok("ok".to_string(), "".to_string(), comment_id.to_string()))
}


#[derive(Serialize,Deserialize)]
struct DeleteComment {
    pub guide_id: i32,
    pub comment_id: i32
}

/// 删除 comment
async fn delete_comment(Query(query):Query<DeleteComment>,cookies:Cookies) -> Json<GuideResponse> {

    // if let Ok(comment) = Comment::fetch_one_by_id(query.comment_id).await.map_err(|err| err.to_string()){
    //
    // }
    // Comment::delete_by_id(query.comment_id).await;

    let user = get_user_from_cookies(cookies).await;
    // println!("{:#?}",user);
    let comment = Comment::fetch_one_by_id(query.comment_id).await.map_err(|err| err.to_string());

    if let Err(err) = user {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    if let Err(err) = comment {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    let user = user.unwrap();
    let comment = comment.unwrap();

    //1. 验证 comment是否是当前用户发送的

    if comment.author_id != user.id {   //不是当前用户发送的评论
        // return Json(serde_json::json!({
        //     "discription":"不允许删除他人的评论！",
        //     "status":"ok"
        // }))
        return Json(GuideResponse::err("不允许删除他人的评论！".to_string(), "".to_string(), "".to_string()));
    }

    //2. 从comments表中删除该comment
    if let Err(res) = Comment::delete_by_id(query.comment_id).await.map_err(|err| err.to_string()){
        return Json(GuideResponse::err(res, "".to_string(), "".to_string()));
    }
    
    //3. 将Guide对象中包含的该评论的评论号码删除

    if let Err(res) = Guide::pop_comment_by_id(query.guide_id, query.comment_id).await.map_err(|err| err.to_string()) {
        println!("That is the problem!!");
        println!("guide_id:{},comment_id:{}",query.guide_id,query.comment_id);

        return Json(GuideResponse::err(res, "".to_string(), "".to_string()));
    }

    // Json(serde_json::json!({
    //     "discription":"删除评论成功！",
    //     "status":"ok"
    // }))
    Json(GuideResponse::ok("删除评论成功！".to_string(), "".to_string(), "".to_string()))

}

/// 更新攻略评论
async fn update_comment(Json(comment):Json<UpdateComment>,cookies:Cookies) -> Json<GuideResponse> {

    // 更新comment
    // if let Err(err) = Comment::update_all_by_id(comment.id, comment.content, comment.rate, "status".to_string()).await.map_err(|err| err.to_string()){
    //     return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    // }

    if let Err(err) = Comment::update_part_by_id(comment.id, comment.content, comment.rate).await.map_err(|err| err.to_string()){
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }

    Json(GuideResponse::ok("更新评论成功".to_string(), "".to_string(), "".to_string()))
}

/// 获取所有作者是当前用户的攻略
async fn get_all_guides_written_by_current_user(cookies:Cookies) -> Json<Vec<Guide>>{
    let user = get_user_from_cookies(cookies).await.unwrap();
    println!("user.id:{}",user.id);
    let res = Guide::fetch_all_by_author_id(user.id).await.unwrap();

    Json(res)
}

/// 发表攻略
async fn make_guide(Json(guide): Json<CreateGuide>,cookies:Cookies) -> Json<GuideResponse>{
    let user = get_user_from_cookies(cookies).await;

    if let Err(err) = user {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    let user = user.unwrap();

    let guide_id = Guide::insert(user.id, guide.guide_type, guide.content, guide.image, vec![])
    .await.map_err(|err| err.to_string());
    if let Err(err) = guide_id {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    let guide_id = guide_id.unwrap();

    Json(GuideResponse::ok("发表攻略成功！".to_string(), guide_id.to_string(), "".to_string()))

}

/// 更新攻略
async fn update_guide(Json(guide):Json<UpdateGuide>,cookies:Cookies) -> Json<GuideResponse> {
    // let res = Guide::update_all_by_id(guide.id, guide.guide_type, guide.content, guide.image, comments, status)
    let res = Guide::update_part_by_id(guide.id, guide.guide_type, guide.content, guide.image).await.map_err(|err| err.to_string());
    if let Err(err) = res {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    Json(GuideResponse::ok("更新攻略成功！".to_string(), guide.id.to_string(), "".to_string()))
}

/// 图片不变时，更新攻略
async fn update_guide2(Json(guide):Json<UpdateGuide2>,cookies:Cookies) -> Json<GuideResponse>{
    let res = Guide::update_type_and_content_by_id(guide.id, guide.guide_type, guide.content).await.map_err(|err| err.to_string());
    if let Err(err) = res {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    Json(GuideResponse::ok("更新攻略成功！".to_string(), guide.id.to_string(), "".to_string()))
}


#[derive(Serialize,Deserialize)]
struct DeleteGuide {
    pub guide_id: i32
}

/// 删除 guide
async fn delete_guide(Query(query):Query<DeleteGuide>,cookies:Cookies) -> Json<GuideResponse> {
    let user = get_user_from_cookies(cookies).await;
    let guide = Guide::fetch_one_by_id(query.guide_id).await.map_err(|err| err.to_string());

    if let Err(err) = user {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    if let Err(err) = guide {
        return Json(GuideResponse::err(err, "".to_string(), "".to_string()));
    }
    let user = user.unwrap();
    let guide = guide.unwrap();

    //1. 验证 guide是否是当前用户发送的

    if guide.author_id != user.id {   //不是当前用户发送的评论
        return Json(GuideResponse::err("不允许删除他人的评论！".to_string(), "".to_string(), "".to_string()));
    }

    //2. 从guide表中删除该guide对象
    if let Err(res) = Guide::delete_by_id(query.guide_id).await.map_err(|err| err.to_string()){
        return Json(GuideResponse::err(res, "".to_string(), "".to_string()));
    }
    
   
    Json(GuideResponse::ok("删除攻略成功！".to_string(), "".to_string(), "".to_string()))

}



#[derive(Serialize,Deserialize)]
struct AddFriendGuide{
    pub guide_id:i32
}

// 请求添加攻略作者为好友
async fn apply_for_friend(Query(query): Query<AddFriendGuide>,cookies:Cookies) -> Json<GuideResponse> {
    let guide = Guide::fetch_one_by_id(query.guide_id).await.unwrap();
    let user = cookie::get_user_from_cookies(cookies).await.unwrap();
    let res = user.apply_for_new_friend(guide.author_id).await;
    if let Err(err) = res {
        return Json(GuideResponse::err(err.to_string(), "".to_string(), "".to_string()));
    } 

    Json(GuideResponse::ok("请求发送成功！".to_string(), "".to_string(), "".to_string()))
}
#[derive(Serialize,Deserialize)]
struct RecomGuide{
    pub guide_id:i32
}

/// 将攻略推荐给好友
async fn recommend_to_friend(Query(query): Query<RecomGuide>,cookies:Cookies) -> Json<GuideResponse> {
    let user = get_user_from_cookies(cookies).await.unwrap();

    for friend_id in user.friends {
        if let Ok(friend) = User::fetch_one_by_id(friend_id).await{
            // friend.push
            let res = friend.push_recom_guide(query.guide_id).await;
            if let Err(err) = res {
                return Json(GuideResponse::err(err.to_string(), "".to_string(), "".to_string()));
            }
        }
    }

    // Json()
    Json(GuideResponse::ok("请求发送成功！".to_string(), "".to_string(), "".to_string()))
}